package com.ruoyi.eqmonitor.controller;

import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.eqmonitor.domain.OptDeviceMonitorLastData;
import com.ruoyi.eqmonitor.dtos.*;
import com.ruoyi.eqmonitor.exception.OpentsdbException;
import com.ruoyi.eqmonitor.service.IOptDeviceMonitorAnalyseDataService;
import com.ruoyi.eqmonitor.service.IOptDeviceMonitorLastDataService;
import com.ruoyi.eqmonitor.utils.Constant;
import com.ruoyi.eqmonitor.utils.OpenTSDBUtils;
import com.ruoyi.eqmonitor.vo.OptDeviceMonitorLastDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.opentsdb.client.bean.request.SubQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;

import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.core.utils.poi.ExcelUtil;

import com.ruoyi.common.core.web.page.TableDataInfo;

/**
 * 设备监测最新实时数据
 * @author ruoyi
 * @date 2022-11-25
 */
@Api("设备监测最新实时数据")
@RestController
@RequestMapping("/data")
public class OptDeviceMonitorLastDataController extends BaseController{
    @Autowired
    private IOptDeviceMonitorLastDataService optDeviceMonitorLastDataService;
    /**
     * 查询设备监测最新实时数据分页
     */
    @ApiOperation("查询设备监测最新实时数据分页")
    @GetMapping("/page")
    public TableDataInfo page(OptDeviceMonitorLastDataVo optDeviceMonitorLastData) {
        startPage();
        List<OptDeviceMonitorLastDataVo> list = optDeviceMonitorLastDataService.selectOptDeviceMonitorLastDataPage(optDeviceMonitorLastData);
        TableDataInfo dataTable = getDataTable(list);
        List<String> resultList = new ArrayList<>();
        list.forEach(optDeviceDto -> {
            resultList.add(Base64.getEncoder().encodeToString(JSONObject.toJSONString(optDeviceDto).getBytes(StandardCharsets.UTF_8)));
        });
        dataTable.setRows(resultList);

        return dataTable;
    }
    /**
     * 查询设备监测最新实时数据列表
     */
    @ApiOperation("查询设备监测最新实时数据列表")
    @GetMapping("/list")
    public TableDataInfo<?> list(OptDeviceMonitorLastData optDeviceMonitorLastData){
        List<OptDeviceMonitorLastData> list = optDeviceMonitorLastDataService.selectOptDeviceMonitorLastDataList(optDeviceMonitorLastData);
        return getDataTable(list.stream().map(item -> {
            Map<String, Object> map = BeanUtil.beanToMap(item);
            // 自定义这几个要显示年月日不显示时分秒
            if (Constant.MonitorInfo.getCustomInfoByCode(item.getCode()) != null) {
                map.put("monitorTime",  DateUtil.formatDate(item.getMonitorTime()));
            } else {
                map.put("monitorTime", DateUtil.formatDateTime(item.getMonitorTime()));
            }
            map.put("installTime", DateUtil.formatDateTime(item.getInstallTime()));
            return map;
        }).collect(Collectors.toList()));
    }
    @Autowired
    private IOptDeviceMonitorAnalyseDataService iOptDeviceMonitorAnalyseDataService;
    /**
     * 重新分析给定时间的日累计数据
     */
    @ApiOperation("重新分析给定时间的日累计数据")
    @Log(title = "设备最新实时数据", businessType = BusinessType.UPDATE)
    @PostMapping("/reAnalysis")
    public AjaxResult reAnalysis(@RequestBody Map<String, Object> map) {
        Date date = MapUtil.getDate(map, "date");
        Date beginDate = MapUtil.getDate(map, "beginDate");
        Date endDate = MapUtil.getDate(map, "endDate");
        DateTime toDay = DateUtil.beginOfDay(DateUtil.date());
        if (date != null) {
            if (DateUtil.isSameDay(date, toDay) || date.after(toDay)) {
                return AjaxResult.error("不能分析当天或未来的数据");
            }
            // 这个函数统计的是入参前一天的日期, 所以这里要offset一下
            date = DateUtil.offsetDay(date, 1);
            iOptDeviceMonitorAnalyseDataService.analyseDailyAccumulation(date, false);
            return AjaxResult.success("分析成功");
        } else if (beginDate != null && endDate != null) {
            // 先统一一下日期的格式, 比如分析2021-01-01到2021-01-03的数据, 入参也是这样的格式
            if (DateUtil.isSameDay(endDate, toDay) || endDate.after(toDay)) {
                // 转换为前一天的日期
                endDate = DateUtil.offsetDay(endDate, -1);
            }
            // 因为代码逻辑是offsetDay, 所以这里要向后推一天, 才能分析到2021-01-01到2021-01-03的数据
            DateUtil.rangeToList(DateUtil.offsetDay(beginDate, 1), DateUtil.offsetDay(endDate, 1), DateField.DAY_OF_YEAR).forEach(item -> {
                iOptDeviceMonitorAnalyseDataService.analyseDailyAccumulation(item, false);
            });
            return AjaxResult.success("根据日期范围，分析成功");
        }
        return AjaxResult.error("日期格式错误");
    }
    /**
     * 根据id查询设备最新实时数据明细
     */
    @ApiOperation("根据id查询设备最新实时数据明细")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id){
        return AjaxResult.success(optDeviceMonitorLastDataService.selectOptDeviceMonitorLastDataById(id));
    }

    /**
     * 导出设备监测最新实时数据列表
     */
    @ApiOperation("导出设备监测最新实时数据列表")
    @Log(title = "设备监测最新实时数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, OptDeviceMonitorLastData optDeviceMonitorLastData){
        List<OptDeviceMonitorLastData> list = optDeviceMonitorLastDataService.selectOptDeviceMonitorLastDataList(optDeviceMonitorLastData);
        ExcelUtil<OptDeviceMonitorLastData> util = new ExcelUtil<OptDeviceMonitorLastData>(OptDeviceMonitorLastData.class);
        util.exportExcel(response, list, "设备监测最新实时数据数据");
    }
    /**
     * 导出最新实时数据列表
     */
    @ApiOperation("导出最新实时数据列表")
    @Log(title = "设备实时数据", businessType = BusinessType.EXPORT)
    @PostMapping("/exportPage")
    public void export(HttpServletResponse response, OptDeviceMonitorLastDataVo optDeviceMonitorLastData) {
        List<OptDeviceMonitorLastDataVo> list = optDeviceMonitorLastDataService.selectOptDeviceMonitorLastDataPage(optDeviceMonitorLastData);
        ExcelUtil<OptDeviceMonitorLastDataVo> util = new ExcelUtil<>(OptDeviceMonitorLastDataVo.class);
        util.exportExcel(response, list, "设备实时数据");
    }
    /**
     * 泵站周边的流量监测仪-瞬时流量+日累积流量
     */
    @ApiOperation("泵站周边的流量监测仪-瞬时流量+日累积流量")
    @GetMapping(value = "/selectFlow")
    public AjaxResult selectFlow() throws OpentsdbException, ParseException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectFlow());
    }

    /**
     * 管道流量监测仪-流量
     */
    @ApiOperation("管道流量监测仪-流量")
    @GetMapping(value = "/selectGuandao")
    public AjaxResult selectGuandao() throws ParseException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectGuandao());
    }

    /**
     * 氨氮一体机-流量-河道报警
     */
    @ApiOperation("氨氮一体机-流量-河道报警")
    @GetMapping("/riverwayFlow")
    public AjaxResult riverwayFlow() throws ParseException, OpentsdbException {
        CockpitRiverwayAlarmDto dto = new CockpitRiverwayAlarmDto();
        dto.setAlarmCode(0);
        dto.setRenovateState(0);
        return AjaxResult.success(optDeviceMonitorLastDataService.riverwayFlow(dto));
    }

    /**
     * 一杠式河道监测站-液位-河道报警
     */
    @ApiOperation("一杠式河道监测站-液位-河道报警")
    @GetMapping("/riverwayLiquidLevel")
    public AjaxResult riverwayLiquidLevel() throws ParseException, OpentsdbException {
        CockpitRiverwayAlarmDto dto = new CockpitRiverwayAlarmDto();
        dto.setAlarmCode(0);
        dto.setRenovateState(0);
        return AjaxResult.success(optDeviceMonitorLastDataService.riverwayLiquidLevel(dto));
    }

    /**
     * 10台氨氮+流量+液位
     * @param datetime 时间
     * @param state 0年、1月、2日
     */
    @ApiOperation("10台氨氮+流量+液位(年月日)")
    @GetMapping(value = "/selectAnDanLiuLiangNYR")
    public AjaxResult selectAnDanLiuLiangNYR(String datetime , Integer state) throws ParseException, IllegalAccessException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectAnDanLiuLiangNYR(datetime,state));
    }

    /**
     * 氨氮一体机水质实时数据(根据设备名称查询当天水质数据)
     * @param deviceName 设备名称
     * @param state 空：当天，2:近一个月数据
     */
    @ApiOperation("氨氮一体机水质实时数据(根据设备名称查询当天水质数据)")
    @GetMapping("/selectAnDanShuiZhi")
    public AjaxResult selectAnDanShuiZhi(String deviceName,Integer state) throws ParseException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectAnDanShuiZhi(deviceName,state));
    }

    /**
     * 河道监测实时数据-前一个月数据（根据传入的起末时间，获取往前一个月相应的起末时间（月度环比））
     */
    @ApiOperation("河道监测实时数据-前一个月")
    @GetMapping("/selectRiverwayMonitorLastMonth")
    public AjaxResult selectRiverwayMonitorLastMonth(RiverwayMonitorDto dto) throws ParseException, IllegalAccessException, OpentsdbException {
        Date beginTimeDate = dto.getBeginTimeDate();
        Date endTimeDate = dto.getEndTimeDate();
        //获取上个月时间并转为时间戳
        dto.setBeginTime(DateUtils.getLastMonth(beginTimeDate).getTime());
        dto.setEndTime(DateUtils.getLastMonth(endTimeDate).getTime());
        return AjaxResult.success(optDeviceMonitorLastDataService.selectRiverwayMonitor(dto));
    }

    /**
     * 判断当天是否下雨
     */
    @ApiOperation("判断当天是否下雨")
    @GetMapping("/rainfall")
    public AjaxResult selectRainfall() throws ParseException, OpentsdbException {
        RiverwayMonitorDto dto = new RiverwayMonitorDto();
        dto.setState(3);
        //起始时间为当天0点时间，结束时间为当前时间
        Date date = new Date();
        dto.setBeginTime(DateUtils.getDayMin(date).getTime());
        dto.setEndTime(date.getTime());
        return AjaxResult.success(optDeviceMonitorLastDataService.selectRainfall(dto));
    }

    /**
     * 根据设备编码查询近一个月的（氨氮，流量，液位三种监测类型）数据
     * @param deviceCode 设备编码
     */
    @ApiOperation("根据设备编码查询近一个月数据")
    @GetMapping("/monthCOD")
    public AjaxResult selectMonthCOD(String deviceCode) throws ParseException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectMonthCOD(deviceCode));
    }

    /**
     * 根据站点id查询井盖检测仪实时数据
     * @param siteId 站点id
     */
    @ApiOperation("井盖检测仪")
    @GetMapping("/wellLid")
    public AjaxResult selectWellLid(String siteId) throws ParseException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectWellLid(siteId));
    }

    /**
     * 河道监测数据
     */
    @ApiOperation("河道监测数据")
    @GetMapping("/selectRiverwayMonitor")
    public AjaxResult selectRiverwayMonitor(RiverwayMonitorDto dto) throws ParseException, IllegalAccessException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectRiverwayMonitor(dto));
    }

    /**
     * 河道监测实时数据-导出
     */
    @ApiOperation("河道监测数据-导出")
    @Log(title = "河道监测数据-导出", businessType = BusinessType.EXPORT)
    @PostMapping("/selectRiverwayMonitor/export")
    public void export(HttpServletResponse response, RiverwayMonitorDto dto) throws ParseException, OpentsdbException {
        List<RiverwayMonitorExport> list = optDeviceMonitorLastDataService.selectRiverwayMonitorExport(dto);
        ExcelUtil<RiverwayMonitorExport> util = new ExcelUtil<RiverwayMonitorExport>(RiverwayMonitorExport.class);
        util.exportExcel(response, list, "河道监测实时数据");
    }

    /**
     * 水情监测数据统计
     */
    @ApiOperation("水情监测数据统计")
    @GetMapping("/selectWaterCondition")
    public AjaxResult selectWaterCondition(WaterQualityReportDto dto) throws ParseException, OpentsdbException {
        //  创建monitorCode过滤器 过滤监测数据
        SubQuery.Filter monitorCodeFilter = OpenTSDBUtils.createMonitorCodeFilter(
                Constant.MonitorInfo.M_0x0592.getCode(),
                Constant.MonitorInfo.M_0x05D1.getCode());
        return AjaxResult.success(optDeviceMonitorLastDataService.selectWaterCondition(dto,monitorCodeFilter));
    }

    /**
     * 水情监测数据统计-导出
     */
    @ApiOperation("水情监测数据统计-导出")
    @Log(title = "水情监测数据统计-导出", businessType = BusinessType.EXPORT)
    @PostMapping("/selectWaterCondition/export")
    public void selectWaterConditionExport(HttpServletResponse response,WaterQualityReportDto dto) throws ParseException, OpentsdbException {
        //  创建monitorCode过滤器 过滤监测数据
        SubQuery.Filter monitorCodeFilter = OpenTSDBUtils.createMonitorCodeFilter(
                Constant.MonitorInfo.M_0x0592.getCode(),
                Constant.MonitorInfo.M_0x05D1.getCode());
        List<WaterConditionExport> list = optDeviceMonitorLastDataService.selectWaterConditionExport(dto, monitorCodeFilter);
        ExcelUtil<WaterConditionExport> util = new ExcelUtil<WaterConditionExport>(WaterConditionExport.class);
        util.exportExcel(response, list, "水情监测数据统计");
    }

    /**
     * 水情数据分析
     */
    @ApiOperation("水情数据分析")
    @GetMapping("/selectWaterConditionAnalyse")
    public AjaxResult selectWaterConditionAnalyse(WaterConditionAnalyseDto dto) throws ParseException, OpentsdbException {
        return AjaxResult.success(optDeviceMonitorLastDataService.selectWaterConditionAnalyse(dto));
    }

    /**
     * 水质数据报表
     */
    @ApiOperation("水质数据报表")
    @GetMapping("/selectWaterQualityReport")
    public AjaxResult selectWaterQualityReport(WaterQualityReportDto dto) throws ParseException, OpentsdbException {
        SubQuery.Filter monitorCodeFilter = OpenTSDBUtils.createMonitorCodeFilter(
                Constant.MonitorInfo.M_0x0527.getCode(),
                Constant.MonitorInfo.M_0x0523.getCode(),
                Constant.MonitorInfo.M_0x0528.getCode());
        return AjaxResult.success(optDeviceMonitorLastDataService.selectWaterCondition(dto,monitorCodeFilter));
    }

    /**
     * 水质数据报表-导出
     */
    @ApiOperation("水质数据报表-导出")
    @Log(title = "水质数据报表-导出", businessType = BusinessType.EXPORT)
    @PostMapping("/selectWaterQualityReport/export")
    public void selectWaterQualityReportExport(HttpServletResponse response,WaterQualityReportDto dto) throws ParseException, OpentsdbException {
        SubQuery.Filter monitorCodeFilter = OpenTSDBUtils.createMonitorCodeFilter(
                Constant.MonitorInfo.M_0x0527.getCode(),
                Constant.MonitorInfo.M_0x0523.getCode(),
                Constant.MonitorInfo.M_0x0528.getCode());
        List<WaterConditionExport> list = optDeviceMonitorLastDataService.selectWaterConditionExport(dto, monitorCodeFilter);
        ExcelUtil<WaterConditionExport> util = new ExcelUtil<WaterConditionExport>(WaterConditionExport.class);
        util.exportExcel(response, list, "水质数据报表");
    }
    
}
